package org.example.util;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.example.csv.CSVData;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CSVUtils {

    private static CSVFormat GEAFLOW = CSVFormat.DEFAULT.builder()
            .setHeader()
            .setSkipHeaderRecord(true)
            .setDelimiter("|")
            .setIgnoreEmptyLines(true)
            .build();

    public static CSVData read(Path p) {
        CSVData csvData;
        try {
            Reader in = new BufferedReader(new FileReader(p.toFile()));
            CSVParser parser = GEAFLOW.parse(in);
            List<CSVRecord> records = parser.getRecords();
            csvData = new CSVData(parser.getHeaderNames(), parser.getHeaderMap());
            List<String[]> lines = new ArrayList<>();
            for (CSVRecord record : records) {
                lines.add(record.values());
            }
            csvData.setLines(lines);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return csvData;
    }

    public static void write(Path p, CSVData csvData) {
        File file = p.toFile();
        try {
            FileWriter writer = new FileWriter(file);
            CSVPrinter csvPrinter = new CSVPrinter(writer, GEAFLOW);
            csvPrinter.printRecord(csvData.getHeaders());
            List<String[]> lines = csvData.getLines();
            for (String[] line : lines) {
                csvPrinter.printRecord((Object[]) line);
            }
            csvPrinter.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Deprecated
    public static CSVData read(String filePath) {
        CSVData csvData;
        try {
            Reader in = new FileReader(getFileAbsolutePath(filePath));
            Iterable<CSVRecord> records = CSVFormat.EXCEL.parse(in);
            int idx = 0;
            csvData = new CSVData();
            for (CSVRecord record : records) {
                String column = record.get(0);
                List<String> line = parseColumn(column);
                if (idx == 0) {
                    csvData.setHeaders(line);
                } else {
                    csvData.addLine(line.toArray(new String[0]));
                }
                idx++;
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return csvData;
    }

    @Deprecated
    public static void write(String filePath, CSVData csvData) {
        try {
            File file =
                    new File(
                            CSVUtils.class.getClassLoader().getResource(".").getFile()
                                    + "/"
                                    + filePath);
            FileWriter writer = new FileWriter(file);
            CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT);
            csvPrinter.printRecord(constructColumn(csvData.getHeaders()));
            List<String[]> lines = csvData.getLines();
            for (String[] line : lines) {
                csvPrinter.printRecord(constructColumn(line));
            }
            csvPrinter.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static List<String> parseColumn(String column) {
        return Arrays.asList(column.split("\\|"));
    }

    private static String constructColumn(List<String> line) {
        return String.join("|", line);
    }

    private static String constructColumn(String[] line) {
        return String.join("|", line);
    }

    private static String getFileAbsolutePath(String relativePath) {
        URL res = CSVUtils.class.getClassLoader().getResource(relativePath);
        File file;
        try {
            assert res != null;
            file = Paths.get(res.toURI()).toFile();
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        return file.getAbsolutePath();
    }
}
